home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / util / cli / mkms_1_35.lha / mkms / mkms.c < prev    next >
C/C++ Source or Header  |  1994-10-21  |  15KB  |  510 lines

  1. /*
  2.  *    mkms: create a shell script to mail a specified list
  3.  *          of files to a specified list of addresses with
  4.  *          a specified list of subjects. with aliases in
  5.  *          an rc file.  do I sound confused?
  6.  *
  7.  *    history:
  8.  *          30SEP94: begun, first usage, basically refitted 'mkfscript'
  9.  *                    to deal with the mail script instead of ftp.
  10.  *          05OCT94: added ability to have aliases for user@address
  11.  *          06OCT94: added the 'find single alias', 'list aliases'
  12.  *                and the 'echo' options.
  13.  *
  14.  *    Copyright (c)1994 by Eric R. Augustine.  Absolute freeware -  do
  15.  *    with it what you wish except sell it or remove this copyright notice.
  16.  *
  17.  *    I may be contacted via internet e-mail: gort@shell.portal.com
  18.  */
  19.  
  20. #include <nlist.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <time.h>
  25. #include <unistd.h>
  26. #include <sys/stat.h>
  27. #include <sys/types.h>
  28.  
  29. #define VERSION "1.35"
  30.  
  31. #define TRUE  1
  32. #define FALSE 0
  33.  
  34. char *progname = "mkms";
  35. char *rcfile   = "/.mkmsrc";
  36.  
  37. typedef int bool;
  38.  
  39. bool listal = FALSE;
  40.  
  41. struct filestr {
  42.    char  *destination;
  43.    char  *message;
  44.    char  *subject;
  45. };
  46.  
  47. struct alias {
  48.     char  *name;
  49.     char  *real;
  50. };
  51.  
  52.  
  53. main(int argc, char *argv[]) {
  54.    FILE       *ifp,*tfp,*ofp;
  55.    bool       mkecho    = FALSE;
  56.    bool       geta = FALSE;
  57.    bool       prout = FALSE;
  58.    bool       stdprt = FALSE;
  59.    bool       rdstdin = FALSE;
  60.    bool       addlns = FALSE;
  61.    bool       ignore = FALSE;
  62.    bool       fsalias = FALSE;
  63.    bool    mkftp = FALSE;
  64.    bool    fdesc = FALSE;
  65.    char       *infile,*outfile,*curstring,*filenm;
  66.    char       *tempname, *site, *dstring, *repstr = NULL;
  67.    char    *aliasf;
  68.    char       buffer[BUFSIZ];
  69.    char    *getalias(char *);
  70.    extern  char *optarg;
  71.    extern  int  optind;
  72.    extern  int  opterr;
  73.    int     c,d,cc,length,elength,flength,linecount,rcerror;
  74.    int     scount = 0,fdelay = 1;
  75.    struct  filestr entry;
  76.    struct  stat stbuf,rcbuf;
  77.    struct  alias al;
  78.    struct  tm *local_time;
  79.    size_t  dlen = 0;
  80.    time_t  now, time();
  81.    void    usage(void);
  82.    void    error(char *, char *);
  83.    void    listrc(void);
  84.    void    findsinglealias(char *);
  85.    void    pversion(void);
  86.  
  87.    progname = argv[0];                           /* whatever program renamed to */
  88.  
  89.    if(argc < 2 ) {                               /* make sure minimal usage valid */
  90.       usage();
  91.       exit(1);
  92.    }
  93.  
  94.    while((d = getopt(argc, argv, "acdelnsvFIf:o:i:S:")) != EOF) {
  95.          switch(d) {
  96.             case 'I':                            /* count output and print count */
  97.                   ignore = TRUE;
  98.                   break;
  99.             case 'l':                            /* list all the aliases */
  100.                listal = TRUE;
  101.                break;
  102.             case 'c':                            /* print to stdout */
  103.                ofp = stdout;
  104.                stdprt = TRUE;
  105.                break;
  106.             case 'e':                            /* add lines to make script echo */
  107.                mkecho= TRUE;
  108.                break;
  109.             case 'f':                            /* find an alias in the rc */
  110.                aliasf = optarg;
  111.                fsalias = TRUE;
  112.                break;
  113.             case 'n':                            /* how many lines and chars written */ 
  114.                prout = TRUE;
  115.                break;
  116.             case 's':                            /* read from stdin */
  117.                ifp = stdin;
  118.                rdstdin = TRUE;
  119.                break;
  120.             case 'a':                            /* append more lines */
  121.                addlns = TRUE;
  122.                break;
  123.             case 'F':                            /* make an ncftp script */
  124.                mkftp = TRUE;
  125.                break;
  126.             case 'v':                            /* print version and copyright info */
  127.                pversion();
  128.                exit(0);
  129.                break;
  130.             case 'o':                            /* get outfile */
  131.                outfile = optarg;
  132.                break;
  133.             case 'i':                            /* get infile */
  134.                infile = optarg;
  135.                break;
  136.             case 'd':                            /* add file descriptions for ftp scripts */
  137.                fdesc = TRUE;
  138.                break;
  139.             case 'S':                            /* get ftp site */
  140.                site = optarg;
  141.                break;
  142.             default:                             /* user error */
  143.                fprintf(stderr,"%s: unknown option '%c'\n",progname,d);
  144.                usage();
  145.                exit(2);
  146.                break;
  147.          }
  148.    }
  149. argc -= optind;
  150. argv += optind;
  151.  
  152. /*  catch a few possible problems
  153.  */
  154.    if(addlns)
  155.       stdprt = FALSE;
  156.    if(mkftp == FALSE)
  157.       fdesc = FALSE;
  158.       
  159.  
  160. /*  stat rcfile and set geta accordingly
  161.  */
  162.    rcfile = strcat(getenv("HOME"),rcfile);
  163.    rcerror = stat(rcfile,&rcbuf);
  164.    if(rcerror == 0) {
  165.       geta = TRUE;
  166.       if((rcbuf.st_mode & S_IFMT) == S_IFDIR) {
  167.          error("your rc file is a directory, ignoring",rcfile);
  168.          if(listal)
  169.             exit(1);
  170.          geta = FALSE;
  171.       }
  172.    }
  173.  
  174. /*  get the user's desired delay for ncftp scripts
  175.  */
  176.    if((geta) && (mkftp)) {
  177.        repstr = getalias("fdelay");
  178.        if(repstr != NULL)
  179.           fdelay = atoi(strdup(repstr));
  180.    }       
  181.  
  182. /*  now that we have the user's delay time we
  183.  *  can ignore the rc file.
  184.  */
  185.    if(ignore)
  186.       geta = FALSE;
  187.  
  188.  
  189. /*  switch site for entry in rc file if exists
  190.  */
  191.    if((geta) && (mkftp)) {
  192.       repstr = getalias(site);
  193.       if(repstr != NULL)
  194.          site = strdup(repstr);
  195.    }
  196.  
  197. /*  list contents of rc file
  198.  */
  199.    if(listal) {
  200.       if(geta) {
  201.          listrc();
  202.          exit(0);
  203.       }
  204.       else {
  205.          error("unable to access rc file.","");
  206.          exit(1);
  207.       }
  208.    }
  209.  
  210. /*  find a single alias in the rcfile
  211.  */
  212.    if(fsalias) {
  213.       if(geta) {
  214.          findsinglealias(aliasf);
  215.          exit(0);
  216.       }
  217.       else {
  218.           error("unable to access rc file.","");
  219.           exit(1);
  220.       }
  221.    }
  222.  
  223.  
  224. /*  open needed files for preprocess
  225.  */
  226.    if(rdstdin);
  227.    else {
  228.       stat(infile,&stbuf);                           /* get file status */
  229.       if((stbuf.st_mode & S_IFMT) == S_IFDIR) {      /* ooops, file is a directory */
  230.          error("named infile is a directory","");
  231.          exit(4);                                    /* goon warrior */
  232.       }
  233.       if(!(ifp = fopen(infile,"r"))) {               /* source file */
  234.          error("unable to open file",infile);
  235.          exit(2);                                    /* user error */
  236.       }
  237.    }
  238.    tempname = tmpnam(NULL);                          /* create temp file */
  239.    if(!(tfp = fopen(tempname,"w"))) {
  240.       error("unable to open temporary file stream","");
  241.       exit(3);                                       /* system error */
  242.    }
  243.  
  244. /*  preprocess source file - remove all tabs and reduce
  245.  *  multiple spaces to single spaces.  this makes all 
  246.  *  input files equivalent.
  247.  */
  248.     while((c = fgetc(ifp)) != EOF) {
  249.         if(c == '\t') {
  250.             if(scount < 1)
  251.                 putc(' ',tfp);
  252.             scount++;
  253.         }
  254.         else if(c == ' ') {
  255.             if(scount < 1)
  256.                 putc(' ',tfp);
  257.             scount++;
  258.         }
  259.         else if(c == '\n') {
  260.             scount = 0;
  261.             putc(c,tfp);
  262.         }
  263.         else {
  264.             scount = 0;
  265.             putc(c,tfp);
  266.         }
  267.     }
  268.  
  269.    if(rdstdin);
  270.    else
  271.       fclose(ifp);                                   /* close source file */
  272.    fclose(tfp);                                      /* reopen temp stream */
  273.    if(!(tfp = fopen(tempname,"r"))) {                /* with mode "read" */
  274.       error("unable to open temporary file stream","");
  275.       exit(3);
  276.    }
  277.  
  278. /*  open output file based on command line opts
  279.  */
  280.    if(stdprt);                                       /* print to terminal */
  281.    else
  282.  
  283. /*  append new lines to end of pre-existing file
  284.  */
  285.    if(addlns) {
  286.       if(stat(outfile,&stbuf) == -1)                 /* is old file there? */
  287.         addlns = FALSE;                                     /* no -> reset flag */
  288.       if((stbuf.st_mode & S_IFMT) == S_IFDIR) {      /* ooops, file is a directory */
  289.         error("named outfile is a directory","");
  290.         exit(5);                                     /* goon error */
  291.       }
  292.       if(!(ofp = fopen(outfile,"a"))) {              /* open file mode append */
  293.         error("unable to open old file",outfile);
  294.         exit(1);
  295.       }
  296.     }
  297.     else {
  298.        stat(outfile,&stbuf);                         /* check filetype */
  299.        if((stbuf.st_mode & S_IFMT) == S_IFDIR) {     /* file is a directory */
  300.           error("named outfile is a directory","");
  301.           exit(5);                                   /* goon alert */
  302.        }
  303.        if(!(ofp = fopen(outfile,"w"))) {             /* print to a new file */
  304.          error("unable to open outfile",outfile);
  305.          exit(1);
  306.        }
  307.     }
  308.  
  309. /*  make the script file
  310.  */
  311.    (void)time(&now);                                 /* get date info for header */
  312.    local_time = localtime(&now);
  313.    dstring = asctime(local_time);
  314.    if(addlns == FALSE) {
  315.       cc = fprintf(ofp,"#!/bin/sh -f\n# generated by %s %s %s",progname,VERSION,dstring);
  316.       linecount = 2;
  317.    }
  318.    else if(addlns) {
  319.       cc = fprintf(ofp,"# added %s",dstring);
  320.       linecount = 2;
  321.    }
  322.    while((curstring = fgets(buffer,BUFSIZ,tfp)) != NULL) { /* parse lines */
  323.       entry.destination = strsep(&curstring," ");
  324.       entry.message        = strsep(&curstring," ");
  325.       entry.subject       = strsep(&curstring,"\n\0");
  326.       if(geta) {
  327.          repstr = getalias(entry.destination);
  328.       if(repstr != NULL)
  329.          entry.destination = strdup(repstr);
  330.       }
  331.       if((mkftp) && (fdesc))
  332.          flength = fprintf(ofp,"# %s: %s\n",entry.destination,entry.subject);
  333.       if((mkecho) && (mkftp == FALSE))
  334.          elength = fprintf(ofp,"echo \"sending %s to %s\" ;\n",entry.message,entry.destination);
  335.       if((mkecho) && (mkftp)) 
  336.          elength = fprintf(ofp,"echo \"getting %s/%s\" ;\n",site,entry.destination);   
  337.       if(mkftp == FALSE) 
  338.          length = fprintf(ofp,"mail -s \"%s\" %s < %s ;\n",entry.subject,entry.destination,entry.message);
  339.       if(mkftp) {
  340.          filenm = strdup(entry.destination);
  341.          filenm = strsep(&filenm,".");
  342.          length = fprintf(ofp,"ncftp >& ./%s.ncftp -d %d -r %s/%s/%s & ;\n",filenm,fdelay,site,entry.message,entry.destination);
  343.       }
  344.       if((prout) && (mkecho))
  345.          length += elength;
  346.       if((prout) && (fdesc))
  347.          length += flength;
  348.       if(prout) {
  349.          linecount ++;
  350.          if(fdesc)
  351.             linecount++;
  352.          if(mkecho)
  353.             linecount++;
  354.          cc += length + dlen;
  355.       }
  356.    }
  357.    if((prout) && (addlns == FALSE))                  /* print info on made file */
  358.       fprintf(stderr,"characters: %d\n     lines: %d\n",cc,linecount);
  359.    else 
  360.       if((addlns == TRUE) && (prout == TRUE))
  361.          fprintf(stderr,"characters added: %d\n  lines appended: %d\n",cc,linecount);
  362.       if(stdprt == FALSE)                            /* don't try to close stout */
  363.          fclose(ofp);                                /* close out file */
  364.       fclose(tfp);
  365.       remove(tempname);
  366. }
  367.  
  368. /*  a little instruction for the unknowing
  369.  */
  370. void usage() {
  371.    fprintf(stderr,"Usage: %s [-acdelnsvFI] [-f alias] [-i input] [-S site] [-o output]\n", progname);
  372.    return;
  373. }
  374.  
  375. /*  print version and copyright information 
  376.  */
  377. void pversion(void) {
  378.    printf("mkms is free software.  you may distribute copies of it as long as no\n");
  379.    printf("profit is made from such distribution.  There is no warranty for mkms.\n");
  380.    printf("mkms %s Copyright (c)1994 by Eric R. Augustine.\n",VERSION);
  381.    return;
  382. }
  383.  
  384. /*  simple error messages
  385.  */
  386. void error(char *estring, char *fstring) {
  387.    fprintf(stderr,"%s: ERROR: %s %s\n", progname, estring, fstring);
  388.    return;
  389. }
  390.  
  391. /*  get aliases from rcfile
  392.  */
  393. char *getalias(char *s) {
  394.    FILE   *rfp;
  395.    bool   DONE = FALSE;
  396.    char   buffer[BUFSIZ],*alstr,*retstr = NULL;
  397.    struct alias al;
  398.  
  399.    if(!(rfp = fopen(rcfile,"r"))) {
  400.       error("unable to open rc file",rcfile);
  401.    }
  402.    else {
  403.       while((!feof(rfp) && (alstr = fgets(buffer,BUFSIZ,rfp)) != NULL) && !DONE) {
  404.          if(alstr[1] == '#');  /* eat comments and other garbage */
  405.          else 
  406.             if(alstr[1] == ' ');  
  407.          else 
  408.             if(alstr[1] == '\n');
  409.          else 
  410.             if(alstr[1] == '\t');
  411.          else 
  412.             if(alstr[1] == '\0');
  413.          else {
  414.             al.name = strsep(&alstr," ");
  415.             al.real = strsep(&alstr,"\n\0");
  416.             if(strcmp(s,al.name) == 0) {
  417.                DONE = TRUE;
  418.                retstr = strdup(al.real);
  419.             }
  420.          }
  421.       }
  422.    }
  423.    if(rfp)
  424.       fclose(rfp);
  425.    return retstr;
  426. }
  427.  
  428. /*  list contents of rcfile
  429.  */
  430. void listrc() {
  431.    FILE   *rfp;
  432.    char   buffer[BUFSIZ],*alstr;
  433.    struct alias al;
  434.  
  435.    printf("\nalias = real value\n");
  436.    printf("--------------------------------------------------------------\n");
  437.    if(!(rfp = fopen(rcfile,"r"))) {
  438.       error("unable to open rc file",rcfile);
  439.    }
  440.    else {
  441.       while((alstr = fgets(buffer,BUFSIZ,rfp)) != NULL) {
  442.          if(alstr[1] == '#');  /* eat comments and other garbage */
  443.          else 
  444.             if(alstr[1] == ' ');
  445.          else 
  446.             if(alstr[1] == '\n');
  447.          else 
  448.             if(alstr[1] == '\t');
  449.          else
  450.             if(alstr[1] == '\0');
  451.          else {
  452.             al.name = strsep(&alstr," ");
  453.             al.real = strsep(&alstr,"\n");
  454.             if(strcmp(al.name,"fdelay") == 0);
  455.             else 
  456.                printf("%s = %s\n",al.name,al.real);
  457.          }
  458.       }
  459.    }
  460.    printf("\n");
  461.    close((int)rfp);
  462.    return;
  463. }
  464.  
  465. /*  name says it all.  find a single alias in the
  466.  *  rc file.
  467.  */
  468. void findsinglealias(char *alias) {
  469.    FILE   *rfp;
  470.    bool   found = FALSE;
  471.    char   buffer[BUFSIZ],*alstr;
  472.    struct alias al;
  473.  
  474.    if(!(rfp = fopen(rcfile,"r")))
  475.       error("unable to open rc file",rcfile);
  476.    else {
  477.       while((alstr = fgets(buffer,BUFSIZ,rfp)) != NULL) {
  478.          if(alstr[1] == '#');  /* eat comments and other garbage */
  479.          else 
  480.             if(alstr[1] == ' ');
  481.          else 
  482.             if(alstr[1] == '\n');
  483.          else 
  484.             if(alstr[1] == '\t');
  485.          else 
  486.             if(alstr[1] == '\0');
  487.          else {
  488.             al.name = strsep(&alstr," ");
  489.             al.real = strsep(&alstr,"\n");
  490.             if(strcmp(alias,al.name) == 0) {
  491.                printf("%s\n",al.real);
  492.                found = TRUE;
  493.             }
  494.             else
  495.                if (strcmp(alias,al.real) == 0) {
  496.                   printf("%s\n",al.name);
  497.                   found = TRUE;
  498.                }
  499.          }
  500.       }
  501.       if(!found) 
  502.          printf("%s: %s not found.\n",progname,alias);
  503.    }
  504.    if(rfp)
  505.       fclose(rfp);
  506.    return;
  507. }
  508.  
  509.  
  510.